#!/bin/sh

MODNAME=docker
MODEXEC=dockerd
CONEXEC=containerd

DATA_ROOT="/opt/docker_root"
SHUTDOWN_TOUT=60

BIN_PATH="/opt/$MODNAME/bin"
USR_BIN_PATH="/usr/bin"

CGROUP_PATH="/sys/fs/cgroup"
CHECK_FILE_LIST="/etc/ssl/certs/ca-certificates.crt \
                 /etc/os-release"

IFNAME="docker0"

export PATH="$PATH:$BIN_PATH"

ipv4_mask_width()
{
  case "$1" in
          128.0.0.0) echo  "1";;
          192.0.0.0) echo  "2";;
          224.0.0.0) echo  "3";;
          240.0.0.0) echo  "4";;
          248.0.0.0) echo  "5";;
          252.0.0.0) echo  "6";;
          254.0.0.0) echo  "7";;
          255.0.0.0) echo  "8";;
        255.128.0.0) echo  "9";;
        255.192.0.0) echo "10";;
        255.224.0.0) echo "11";;
        255.240.0.0) echo "12";;
        255.248.0.0) echo "13";;
        255.252.0.0) echo "14";;
        255.254.0.0) echo "15";;
        255.255.0.0) echo "16";;
      255.255.128.0) echo "17";;
      255.255.192.0) echo "18";;
      255.255.224.0) echo "19";;
      255.255.240.0) echo "20";;
      255.255.248.0) echo "21";;
      255.255.252.0) echo "22";;
      255.255.254.0) echo "23";;
      255.255.255.0) echo "24";;
    255.255.255.128) echo "25";;
    255.255.255.192) echo "26";;
    255.255.255.224) echo "27";;
    255.255.255.240) echo "28";;
    255.255.255.248) echo "29";;
    255.255.255.252) echo "30";;
    255.255.255.254) echo "31";;
                  *) echo "32";;
  esac
}

case "$1" in
  start)
        . /opt/$MODNAME/etc/settings
        echo -n "Starting module $MODNAME: "
        if [ "$MOD_DOCKER_ENABLED" != "1" ]; then
                echo "skipped"
                exit 0
        fi
        echo

        RETVAL=0
        echo "  Checking system requirements:"
        echo -n "    Checking /opt filesystem: "
        if [ "`/usr/bin/awk '/opt / {print $3}' /proc/mounts`" = "jffs2" ]; then
                /usr/bin/logger -t $MODNAME "error: bad /opt filesystem, unsupported firmware"
                echo "failed"
                RETVAL=2
        else
                echo "done"
        fi
        echo -n "    Checking $CGROUP_PATH: "
        if [ ! -d $CGROUP_PATH ]; then
                /usr/bin/logger -t $MODNAME "error: $CGROUP_PATH missing, maybe update firmware?"
                echo "failed"
                RETVAL=3
        else
                echo "done"
        fi
        for FILE in $CHECK_FILE_LIST; do
                echo -n "    Checking $FILE: "
                if [ ! -f $FILE ]; then
                        /usr/bin/logger -t $MODNAME "error: $FILE missing, maybe update firmware?"
                        echo "failed"
                        RETVAL=4
                else
                        echo "done"
                fi
        done

        echo -n "  Mounting $CGROUP_PATH: "
        ERR=0
        /bin/grep -q "tmpfs $CGROUP_PATH " /proc/mounts
        if [ $? != 0 ]; then
                /bin/mount -t tmpfs -o nosuid,nodev,noexec,mode=755 tmpfs $CGROUP_PATH || ERR=1
        fi
        /bin/grep -q "cgroup2 $CGROUP_PATH/unified " /proc/mounts
        if [ $? != 0 ]; then
                /bin/mkdir $CGROUP_PATH/unified
                /bin/mount -t cgroup2 -o nosuid,nodev,noexec,relatime,nsdelegate cgroup2 $CGROUP_PATH/unified || ERR=1
        fi
        for CGROUP in $(/usr/bin/awk '!/^#/ {print $1}' /proc/cgroups); do
                /bin/grep -q "cgroup $CGROUP_PATH/$CGROUP " /proc/mounts
                if [ $? != 0 ]; then
                        /bin/mkdir $CGROUP_PATH/$CGROUP
                        /bin/mount -t cgroup -o nosuid,nodev,noexec,relatime,$CGROUP cgroup $CGROUP_PATH/$CGROUP || ERR=1
                fi
        done
        echo 1 > $CGROUP_PATH/memory/memory.use_hierarchy || ERR=1
        if [ $ERR != 0 ]; then
                echo "failed"
                RETVAL=6
        else
                echo "done"
        fi

        echo "  Creating symlinks:"
        for BIN in `ls $BIN_PATH`; do
                [ "$BIN" = "cgi" ] && continue
                echo -n "    $USR_BIN_PATH/$BIN -> $BIN_PATH/$BIN: "
                if [ ! -x $USR_BIN_PATH/$BIN ]; then
                        /bin/ln -s $BIN_PATH/$BIN $USR_BIN_PATH/$BIN
                        if [ $? != 0 ]; then
                                echo "failed"
                                RETVAL=7
                        else
                                echo "done"
                        fi
                else
                        echo "skipped"
                fi
        done

        echo -n "  Creating $MODNAME group: "
        /bin/grep -q $MODNAME /etc/group
        if [ $? != 0 ]; then
                /usr/sbin/addgroup $MODNAME
                if [ $? != 0 ]; then
                        echo "failed"
                        RETVAL=8
                else
                        echo "done"
                fi
        else
                echo "skipped"
        fi

        echo -n "  Mounting data root: "
        if [ "$MOD_DOCKER_DATA_ROOT" != "$DATA_ROOT" ]; then
                /bin/grep -q "$MOD_DOCKER_DATA_ROOT $DATA_ROOT" /proc/mounts
                if [ $? != 0 ]; then
                        [ -d "$DATA_ROOT" ] || mkdir -p "$DATA_ROOT"
                        /bin/mount $MOD_DOCKER_DATA_ROOT $DATA_ROOT 2>/dev/null
                        if [ $? != 0 ]; then
                                echo "failed"
                                RETVAL=9
                        else
                                echo "done"
                        fi
                else
                        echo "done"
                fi
        else
                echo "skipped"
        fi

        echo -n "  Starting $CONEXEC: "
        $BIN_PATH/$CONEXEC --config /opt/$MODNAME/etc/$CONEXEC.toml >>/var/log/$CONEXEC.log 2>&1 &
        if [ $? != 0 ]; then
                echo "failed"
                RETVAL=10
        else
                echo "done"
        fi

        echo -n "  Starting $MODEXEC: "
        if [ -n "$MOD_DOCKER_IPADDR" -a -n "$MOD_DOCKER_NETMASK" ]; then
                BIP="$MOD_DOCKER_IPADDR/`ipv4_mask_width $MOD_DOCKER_NETMASK`"
        else
                BIP="172.17.0.1/16"
        fi
        if [ -n "$MOD_DOCKER_IPADDR6" -a -n "$MOD_DOCKER_PREFIX6" ]; then
                IPV6_OPTS="--ipv6 --fixed-cidr-v6 $MOD_DOCKER_IPADDR6/$MOD_DOCKER_PREFIX6"
                if [ "$MOD_DOCKER_EXPERIMENTAL" = "1" ]; then
                        IPV6_OPTS="$IPV6_OPTS --ip6tables"
                fi
        else
                IPV6_OPTS=""
        fi
        INSEC_REG_OPTS=""
        if [ "$MOD_DOCKER_INSEC_REG_ENABLED" = "1" ]; then
                IDX=1
                while eval ENABLED='$'MOD_DOCKER_INSEC_REG_ENABLED$IDX && [ -n "$ENABLED" ]; do
                        if [ "$ENABLED" = "1" ]; then
                                eval ADDR='$'MOD_DOCKER_INSEC_REG_ADDR$IDX
                                if [ -n "$ADDR" ]; then
                                        INSEC_REG_OPTS="$INSEC_REG_OPTS --insecure-registry $ADDR"
                                        eval PORT='$'MOD_DOCKER_INSEC_REG_PORT$IDX
                                        if [ -n "$PORT" ]; then
                                                INSEC_REG_OPTS="$INSEC_REG_OPTS:$PORT"
                                        fi
                                fi
                        fi
                        IDX=$((IDX+1))
                done
        fi
        if [ "$MOD_DOCKER_DEBUG" = "1" ]; then
                DEBUG_OPTS="--debug"
        else
                DEBUG_OPTS=""
        fi
        if [ "$MOD_DOCKER_EXPERIMENTAL" = "1" ]; then
                EXPERIMENTAL_OPTS="--experimental"
        else
                EXPERIMENTAL_OPTS=""
        fi
        OPTS="--containerd /var/run/$CONEXEC/$CONEXEC.sock \
              --data-root $DATA_ROOT \
              --userland-proxy=false \
              --log-opt max-size=1m \
              --shutdown-timeout $SHUTDOWN_TOUT \
              --bip $BIP \
              $IPV6_OPTS \
              $INSEC_REG_OPTS \
              $DEBUG_OPTS \
              $EXPERIMENTAL_OPTS"
        $BIN_PATH/$MODEXEC $OPTS >>/var/log/$MODEXEC.log 2>&1 &
        if [ $? != 0 ]; then
                echo "failed"
                RETVAL=11
        else
                echo "done"
        fi
	exit $RETVAL
        ;;

  stop)
        echo "Stopping module $MODNAME:"

        echo -n "  Stopping $MODEXEC: "
        /usr/bin/killall $MODEXEC 2>/dev/null
        if [ $? = 0 ]; then
                TOUT=$SHUTDOWN_TOUT
                while /usr/bin/killall -0 $MODEXEC 2>/dev/null; do
                        [ $TOUT -gt 0 ] || break
                        sleep 1
                        TOUT=$((TOUT-1))
                        echo -n "."
                done
                echo " done"
        else
                echo "failed"
        fi

        echo -n "  Stopping $CONEXEC: "
        /usr/bin/killall $CONEXEC 2>/dev/null
        [ $? = 0 ] && echo "done" || echo "failed"

        echo -n "  Stopping interface $IFNAME: "
        /sbin/ifconfig $IFNAME 0.0.0.0 down 2>/dev/null
        [ $? = 0 ] && echo "done" || echo "failed"

        echo -n "  Unmounting data root: "
        /bin/grep -q $DATA_ROOT /proc/mounts
        if [ $? = 0 ]; then
                /bin/umount $DATA_ROOT 2>/dev/null
                [ $? = 0 ] && echo "done" || echo "failed"
        else
                echo "skipped"
        fi
        ;;

  restart)
        $0 stop
        $0 start
        ;;

  status)
        echo -n "Module $MODNAME is "
        /usr/bin/killall -0 $MODEXEC 2>/dev/null
        RETVAL=$?
        if [ $RETVAL = 0 ]; then echo "running"; else echo "stopped"; fi
        exit $RETVAL
        ;;

  du)
        /bin/grep -q $DATA_ROOT /proc/mounts
        if [ $? = 0 ]; then
                /bin/df | /usr/bin/awk -v DATA_ROOT=$DATA_ROOT -f /opt/$MODNAME/awk/du.awk
        else
                echo "Data Root not mounted"
        fi
        ;;

  defaults)
        cp /opt/$MODNAME/etc/defaults /opt/$MODNAME/etc/settings 2>/dev/null
        ;;

  *)
        echo "Usage: $0 {start|stop|restart|status|du|defaults}"
        exit 1
esac
